/*
 * ScoreKeeper class is in charge of keeping track of:
 * strikes, balls, outs, innings and score, hits and errors during a game.
 */

#include "scorekeeper.h"

ScoreKeeper::ScoreKeeper(QVector<Player*> home, int hPitcher, QVector<Player*> away, int aPitcher)
{
    for(int i=0;i<9;i++){
        homeStats.push_back(new GameStatistic());
        awayStats.push_back(new GameStatistic());
    }
    homeScore=0;
    awayScore=0;
    homeHits=0;
    awayHits=0;
    homeErrors=0;
    awayErrors=0;
    strikes=0;
    balls=0;
    outs=0;
    inning=1;
    bottomHalfOfInning=false;
    REGULATION_INNINGS=9;
    MAX_NUMBER_OF_STRIKES=3;
    MAX_NUMBER_OF_BALLS=4;
    MAX_NUMBER_OF_OUTS=3;
    homeLineupPosition=0;
    awayLineupPosition=0;
    setHomeLineUp(home);
    setAwayLineup(away);
    atBat= awayLineup.at(awayLineupPosition);
    awayStats.at(awayLineupPosition)->incrementAtBats();
    first=0;
    second=0;
    third=0;
    homePitcher=hPitcher;
    homeLineup.at(homePitcher)->getPlayerStats().incrementGamesPitched();
    awayPitcher=aPitcher;
    awayLineup.at(awayPitcher)->getPlayerStats().incrementGamesPitched();
}

ScoreKeeper::~ScoreKeeper(){
    delete atBat;
    delete first;
    delete second;
    delete third;
}

int ScoreKeeper::getHomeScore(){
    return homeScore;
}

int ScoreKeeper::getAwayScore(){
    return awayScore;
}

//adds runs to the batting team
void ScoreKeeper::addToScore(int runs){
    if(isBottomHalf()){
        homeScore+=runs;
    }
    else{
        awayScore+=runs;
    }
}

int ScoreKeeper::getHomeHits(){
    return homeHits;
}

int ScoreKeeper::getAwayHits(){
    return awayHits;
}

//adds hits to the batting team;
void ScoreKeeper::incrementHits(){
    if(isBottomHalf()){
        homeHits++;
    }
    else{
        awayHits++;
    }
}

int ScoreKeeper::getHomeErrors(){
    return homeErrors;
}

int ScoreKeeper::getAwayErrors(){
    return awayErrors;
}

//adds errors to the pitching team
void ScoreKeeper::addToErrors(int errors){
    if(isBottomHalf()){
        awayErrors+=errors;
    }
    else{
        homeErrors+=errors;
    }
}

int ScoreKeeper::getStrikes(){
    return strikes;
}

int ScoreKeeper::getBalls(){
    return balls;
}

int ScoreKeeper::getOuts(){
    return outs;
}

int ScoreKeeper::getInning(){
    return inning;
}

bool ScoreKeeper::isBottomHalf(){
    return bottomHalfOfInning;
}


void ScoreKeeper::incrementStrikes(){
    if(strikes==2){
        if(bottomHalfOfInning){
            homeStats.at(homeLineupPosition)->incrementStrikeouts();
            awayStats.at(awayPitcher)->incrementStrikeoutsPitched();
        }
        else{
            awayStats.at(awayLineupPosition)->incrementStrikeouts();
            homeStats.at(homePitcher)->incrementStrikeoutsPitched();
        }

        incrementOuts();
    }
    else{
        strikes++;
    }
}

bool ScoreKeeper::incrementBalls(){
    if(balls==3){
        if(first!=0){
            if(second!=0){
                if(third!=0){
                    addToScore(1);
                }

                if(bottomHalfOfInning){
                    homeStats.at(homeLineupPosition)->incrementWalks();
                    awayStats.at(awayPitcher)->incrementWalksPitched();
                }
                else{
                    awayStats.at(awayLineupPosition)->incrementWalks();
                    homeStats.at(homePitcher)->incrementWalksPitched();
                }
            }
        }
        incrementLineupPosition();
        resetAtBat();
        return true;
    }
    else{
        balls++;
        return false;
    }
}

void ScoreKeeper::incrementOuts(){
    resetAtBat();
    if(bottomHalfOfInning){
        homeStats.at(homePitcher)->incrementInningsPitched();
    }
    else{
        awayStats.at(awayPitcher)->incrementInningsPitched();
    }
    if(outs==2){
        incrementLineupPosition();
        clearBases();
        if(bottomHalfOfInning){
            incrementInning();
        }
        else{
            resetInning();
        }
    }
    else{
        outs++;
    }
}

void ScoreKeeper::incrementInning(){
    resetInning();
    inning++;
}

void ScoreKeeper::toggleBottomHalf(){
    bottomHalfOfInning= !bottomHalfOfInning;
    if(bottomHalfOfInning){
        atBat=homeLineup.at(homeLineupPosition);
        homeStats.at(homeLineupPosition)->incrementAtBats();
    }
    else{
        atBat=awayLineup.at(awayLineupPosition);
        awayStats.at(awayLineupPosition)->incrementAtBats();
    }
}

bool ScoreKeeper::isGameOver(){
    return inning >= REGULATION_INNINGS && homeScore!= awayScore && !bottomHalfOfInning;
}

void ScoreKeeper::resetAtBat(){
    strikes=0;
    balls=0;
}

void ScoreKeeper::resetInning(){
    outs=0;
    resetAtBat();
    toggleBottomHalf();
}

void ScoreKeeper::foulBall(){
    if(strikes<2){
        incrementStrikes();
    }
}

void ScoreKeeper::setHomeLineUp(QVector<Player*> home){
    for(int i=0; i<9; i++){
        homeLineup.push_back(home.at(i));
        homeLineup.at(i)->getPlayerStats().incrementGamesPlayed();
    }
}

void ScoreKeeper::setAwayLineup(QVector<Player*> away){
    for(int i=0; i<9; i++){
        awayLineup.push_back(away.at(i));
        awayLineup.at(i)->getPlayerStats().incrementGamesPlayed();
    }
}

void ScoreKeeper::incrementLineupPosition(){
    if(isBottomHalf()){
        if(homeLineupPosition==8){
            homeLineupPosition=0;
        }
        else{
            homeLineupPosition++;
        }
        atBat=homeLineup.at(homeLineupPosition);
        homeStats.at(homeLineupPosition)->incrementAtBats();
        awayStats.at(awayPitcher)->incrementAtBatsFaced();

    }
    else{
        if(awayLineupPosition==8){
            awayLineupPosition=0;
        }
        else{
            awayLineupPosition++;
        }
        atBat=awayLineup.at(awayLineupPosition);
        awayStats.at(awayLineupPosition)->incrementAtBats();
        homeStats.at(homePitcher)->incrementAtBatsFaced();
    }
    resetAtBat();
}

Player* ScoreKeeper::whosAtBat(){
    if(isBottomHalf()){
        return homeLineup.at(homeLineupPosition);
    }
    else{
        return awayLineup.at(awayLineupPosition);
    }
}

Player* ScoreKeeper::whosOnFirst(){
    return first;
}

Player* ScoreKeeper::whosOnSecond(){
    return second;
}

Player* ScoreKeeper::whosOnThird(){
    return third;
}

void ScoreKeeper::homerun(){
    int count=0;
    if(first != 0){
        count++;
    }
    if(second != 0){
        count++;
    }
    if(third != 0){
        count++;
    }
    addToScore(count+1);
    clearBases();
    incrementLineupPosition();
}

void ScoreKeeper::clearBases(){
    first=0;
    second=0;
    third=0;
}

void ScoreKeeper::single(){
    if(isBottomHalf()){
        homeStats.at(homeLineupPosition)->incrementSingles();
        awayStats.at(awayPitcher)->incrementHitsAllowed();
    }
    else{
        awayStats.at(awayLineupPosition)->incrementSingles();
        homeStats.at(homePitcher)->incrementHitsAllowed();
    }

    incrementLineupPosition();
}

void ScoreKeeper::hitDouble(){
    if(bottomHalfOfInning){
        homeStats.at(homeLineupPosition)->incrementDoubles();
        awayStats.at(awayPitcher)->incrementHitsAllowed();
    }
    else{
        awayStats.at(awayLineupPosition)->incrementDoubles();
        homeStats.at(homePitcher)->incrementHitsAllowed();
    }
    incrementLineupPosition();
}

void ScoreKeeper::triple(){
    if(bottomHalfOfInning){
        homeStats.at(homeLineupPosition)->incrementTriples();
        awayStats.at(awayPitcher)->incrementHitsAllowed();
    }
    else{
        awayStats.at(awayLineupPosition)->incrementTriples();
        homeStats.at(homePitcher)->incrementHitsAllowed();
    }
    incrementLineupPosition();
}

GameStatistic ScoreKeeper::getCurrentPlayerStats(){
    if(isBottomHalf()){
        return *homeStats.at(homeLineupPosition);
    }
    else{
        return *awayStats.at(awayLineupPosition);
    }
}

QVector<GameStatistic*> ScoreKeeper::getHomeStats(){
    return homeStats;
}

QVector<GameStatistic*> ScoreKeeper::getAwayStats(){
    return awayStats;
}

QVector<Player*> ScoreKeeper::getHomeLineup(){
    return homeLineup;
}

QVector<Player*> ScoreKeeper::getAwayLineup(){
    return awayLineup;
}

void ScoreKeeper::setFirst(Player* p){
    first=p;
}

void ScoreKeeper::setSecond(Player* p){
    second=p;
}

void ScoreKeeper::setThird(Player* p){
    third=p;
}

GameStatistic ScoreKeeper::getPlayerStats(Player* p){
    if(isBottomHalf()){
        for(int i=0; i<homeStats.size(); i++){

        }
    }
}
